package edu.umn.cs5115.scheduler.entities;

/**
 * Enum containing days of week, used by calendar.
 * @author grant
 */
public enum Weekday
{
    SUNDAY("Sunday", "Sun.", "Su", 0),
    MONDAY("Monday", "Mon.", "M", 1),
    TUESDAY("Tuesday", "Tue.", "Tu", 2),
    WEDNESDAY("Wednesday", "Wed", "W", 3),
    THURSDAY("Thursday", "Thur.", "Th", 4),
    FRIDAY("Friday", "Fri.", "F", 5),
    SATURDAY("Saturday", "Sat.", "Sa", 6);

    /** Plain English name of the week day. */
    private String name;
    /** Abreviated English name of the week day. */
    private String abbreviatedName;
    /** Very Abbreviated English name of the week day. */
    private String veryAbbreviatedName;
    /** Number of the day in the week. */
    private int dayOfWeek;

    /**
     * Create a new Weekday
     * @param name A plain English name for this Weekday. ("Tuesday")
     * @param abbreviatedName The standard abbreviation for this Weekday ("Tue.")
     * @param veryAbbreviatedName The shortest non-ambiguous name for this Weekday ("Tu")
     * @Param dayOfWeek The number of this weekday in the week.
     */
    private Weekday(String name, String abbreviatedName, String veryAbbreviatedName, int dayOfWeek)
    {
        this.name = name;
        this.dayOfWeek = dayOfWeek;
        this.abbreviatedName = abbreviatedName;
        this.veryAbbreviatedName = veryAbbreviatedName;
    }

    /**
     * Get the name of this weekday.
     * @return The name of the weekday (ie, "Tuesday")
     */
    public String getName()
    {
        return name;
    }

    /**
     * Get the abbreviated name of this weekday.
     * @return The abbreviated name of this weekday. (ie, "Tue.")
     */
    public String getAbbreviatedName()
    {
        return abbreviatedName;
    }

    /**
     * Get the shortest unambiguous name for this weekday.
     * @return The shortest unambiguous abbreviated name for this weekday. (ie, "Tu")
     */
    public String getVeryAbbreviatedName()
    {
        return veryAbbreviatedName;
    }

    /**
     * Get the String representation of this weekday, which is its name.
     * @return The name of the weekday (ie, "Tuesday");
     */
    public String toString()
    {
        return name;
    }

    /**
     * Get the Weekday that comes after this weekday.
     * @return The next day of the week.  (for example, if this was 
     * SATURDAY, the return value is SUNDAY)
     */
    public Weekday getNextDay()
    {
        return getWeekday(dayOfWeek+1);
    }

    /**
     * Get the Weekday that comes before this weekday.
     * @return The previous day of the week.  (for example if this was
     * SUNDAY, the return value is SATURDAY)
     */
    public Weekday getPreviousDay()
    {
        return getWeekday(dayOfWeek-1);
    }

    /**
     * Get a number indicating what day of the week this weekday is.
     * @return The index of the weekday (SUNDAY = 0, MONDAY = 1, ...)
     */
    public int getDayOfWeek()
    {
        return dayOfWeek;
    }

    /**
     * Get the day of a week, based on its numeric value.
     * @param dayOfWeek The number of days after Sunday to get a day of the
     * week for.  It can be 7 or more or less than 0.
     * @return The Weekday corresponding to the day of the week specified.
     * For example, 0 returns SUNDAY, -1 returns SATURDAY, 8 returns MONDAY,
     * and so on.
     */
    public static Weekday getWeekday(int dayOfWeek)
    {
        dayOfWeek %= 7;
        if (dayOfWeek < 0)
            dayOfWeek += 7;
        for(Weekday weekday : Weekday.values())
            if (weekday.getDayOfWeek() == dayOfWeek)
                return weekday;
        // this return statement shouldn't be reached.
        return null;
    }

    /**
     * Defines abbreviation levels for weekdays.
     */
    public static enum AbbreviationLevel
    {
        FULL { public String getLabel(Weekday weekday) { return weekday.getName(); } },
        ABBREVIATED { public String getLabel(Weekday weekday) { return weekday.getAbbreviatedName(); } },
        VERY_ABBREVIATED { public String getLabel(Weekday weekday) { return weekday.getVeryAbbreviatedName(); } };

        public abstract String getLabel(Weekday weekday);
    }
}
